package helpers;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import entities.Categorie;
import entities.DVD;
import entities.ImagesGroup;
import java.util.Arrays;
import java.util.Iterator;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import servlets.LoadServlet;

/*
 * Cette classe permet de constituer notre base de donnée grace à l'API AMAZON
 */
public class AmazonHelper {

    private static final String ENDPOINT = "ecs.amazonaws.com";
    private static final String AWS_ACCESS_KEY_ID = "AKIAJQXAKVNJJ3F5X7SA";
    private static final String AWS_SECRET_KEY = "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";
    private static final SimpleDateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd");
    private static final String[] KEYWORDS = {
        "titanic", "black swan", "inception", "iron man",
        "transformers", "harry potter", "men in black 3",
        "moonrise kingdom", "millénium", "gran torino", "intouchables",
        "glee", "drive", "house", "desperate housewives",
        "ncis", "trust", "saws",
        "rec", "cosmopolis", "slumdog millionaire",
        "Grey's Anatomy", "StreetDance 2", "Le Roi Lion",
        "les experts", "paranormal activity", "la planète des singes",
        "avatar", "aviator", "volver", "Inglourious Basterds",
        "La Ligne Verte", "Million Dollar Baby",
        "Shutter Island", "Léon", "Jurassic Park",
        "stargate", "stargate atlantis", "La vie est belle", "Metropolis",
        "Taken", "Terminator 2", "invictus", "polisse",
        "district9", "the social network", "Dark Shadows"
    };

    static {
        // obligatoire pour faire un binarySearch
        Arrays.sort(KEYWORDS);
    }

    private AmazonHelper() {
    }

    public static void getXML(LoadServlet servlet) {
        File directory = new File(servlet.getServletContext().getRealPath("xml"));

        // création du dossier xml s'il n'existe pas
        if (!directory.exists() || !directory.isDirectory()) {
            directory.mkdir();
        }

        if (directory.exists() && directory.isDirectory()) {
            try {
                // parametre envoyé à Amazon
                Map<String, String> params = new HashMap<String, String>();
                params.put("Service", "AWSECommerceService");
                params.put("Operation", "ItemSearch");
                params.put("SearchIndex", "DVD");
                params.put("ResponseGroup", "Images,ItemAttributes,EditorialReview,BrowseNodes");
                params.put("AssociateTag", "worofvidgam-20");

                // Classe de l'API Amazon
                SignedRequestsHelper helper = SignedRequestsHelper.getInstance(ENDPOINT, AWS_ACCESS_KEY_ID, AWS_SECRET_KEY);
                DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

                // Pour chaque mot clé, on crée le fichier xml, on récupère le flux de donnée et on écrit dans le fichier xml
                for (String keyword : KEYWORDS) {
                    try {
                        File file = new File(directory, keyword.replaceAll("[\\W]", "") + ".xml");

                        if (file.length() == 0) {
                            file.delete();
                        }

                        if (file.createNewFile()) {
                            params.put("Keywords", keyword);
                            URL url = new URL(helper.sign(params));
                            ReadableByteChannel rbc = Channels.newChannel(url.openStream());
                            FileOutputStream fos = new FileOutputStream(file);
                            fos.getChannel().transferFrom(rbc, 0, 1 << 24);
                            System.out.println("#### " + file.getAbsolutePath() + " ####");
                            //recupere les fichiers .xml
                        }

                        parseXML(builder, file, servlet);
                    } catch (SAXException ex) {
                        Logger.getLogger(AmazonHelper.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (ParseException ex) {
                        Logger.getLogger(AmazonHelper.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (IOException ex) {
                        Logger.getLogger(AmazonHelper.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            } catch (ParserConfigurationException ex) {
                Logger.getLogger(AmazonHelper.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalArgumentException ex) {
                Logger.getLogger(AmazonHelper.class.getName()).log(Level.SEVERE, null, ex);
            } catch (UnsupportedEncodingException ex) {
                Logger.getLogger(AmazonHelper.class.getName()).log(Level.SEVERE, null, ex);
            } catch (NoSuchAlgorithmException ex) {
                Logger.getLogger(AmazonHelper.class.getName()).log(Level.SEVERE, null, ex);
            } catch (InvalidKeyException ex) {
                Logger.getLogger(AmazonHelper.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private static void parseXML(DocumentBuilder builder, File file, LoadServlet servlet) throws SAXException, IOException, ParseException {
        Document doc = builder.parse(file);
        NodeList items = doc.getElementsByTagName("Item");

        for (int i = 0; i < items.getLength(); i++) {
            Element item = (Element) items.item(i);
            NodeList images = item.getElementsByTagName("ImageSet");
            Element listPrice = DocumentHelper.getElement(item, "ListPrice");
            String amount = DocumentHelper.getValue(listPrice, "Amount");
            String binding = DocumentHelper.getValue(item, "Binding");
            String releaseDate = DocumentHelper.getValue(item, "ReleaseDate");
            String director = DocumentHelper.getValue(item, "Director");
            /*String ageRating = DocumentHelper.getValue(item, "Feature");*/
            NodeList descriptions = item.getElementsByTagName("Content");

            if (director == null || releaseDate == null || amount == null
                    || images == null || descriptions == null) {
                continue;
            }

            String title = DocumentHelper.getValue(item, "Title");
            Categorie category = servlet.getCategoryFacade().getOrCreate(binding);
            DVD dvd = servlet.getDVDFacade().create(title, category);

            if (dvd == null) {
                continue;
            }

            String description = "";

            for (int j = 0; j < descriptions.getLength(); j++) {
                description += descriptions.item(j).getTextContent() + "<br />";
            }

            dvd.setReleaseDate(FORMAT.parse(releaseDate));
            dvd.setDescription(description);
            dvd.setPrice(Double.parseDouble(amount) / 100);
            dvd.setDirector(director);
            /*dvd.setAgeRating(servlet.getAgeRatingFacade().getByName(ageRating));*/

            for (int j = 0; j < images.getLength(); j++) {
                Element image = (Element) images.item(j);
                ImagesGroup imagesGroup = DocumentHelper.getImagesGroup(servlet, image);

                if (image.getAttribute("Category").equals("primary")) {
                    dvd.setImage(imagesGroup);
                } else {
                    dvd.getImages().add(imagesGroup);
                }
            }

            if (dvd.getImage() == null) {
                Iterator<ImagesGroup> iterator = dvd.getImages().iterator();
                if (iterator.hasNext()) {
                    dvd.setImage(iterator.next());
                    iterator.remove();
                }
            }

            /*NodeList nodes = item.getElementsByTagName("BrowseNode");
            
            for (int j=0; j<nodes.getLength(); j++) {
            Element node = (Element) nodes.item(j);
            String name = DocumentHelper.getValue(node, "Name");
            
            if (name != null) {
            String[] splits = name.split(" - ");
            
            for (String split : splits) {
            if (Arrays.binarySearch(NO_WANTED_TAGS, split) < 0) {
            Tag tag = servlet.getTagFacade().getOrCreate(split);
            
            if (!videoGame.getTags().contains(tag)) {
            videoGame.getTags().add(tag);
            }
            }
            }
            }
            }*/

            /*NodeList features = item.getElementsByTagName("Feature");
            
            for (int j=0; j<features.getLength(); j++) {
            Element feature = (Element) features.item(j);
            dvd.getFonctionnalites().add(new Fonctionnalite(feature.getTextContent()));
            }*/

            servlet.getDVDFacade().edit(dvd);
            System.out.println("#### " + file.getName() + " #### " + title + " #### " + binding + " ####");
        }
    }
}